// ==UserScript==
// @name        jsHook
// @author      white
// @version     1.0
// @namespace   white/debugger
// @author      white
// @match       *://*/*
// @license     MIT
// @grant       GM_registerMenuCommand
// @grant       GM_setValue
// @grant       GM_getValue
// @grant       GM_deleteValue
// @run-at      document-start
// @icon        
// ==/UserScript==
(function () {
  "use strict";
  const StorageUtil = {
    keys: {
      functionState: "db/functionState",
    },
    getDefaultFunctionState: function () {
      return {
        /* cookie */
        isHookCookie: {
          value: false,
          name: "hook cookie",
          type: "switch",
          describe:
            "hook当前网页的所有cookie，如果未指定“捕获cookie name”则hook所有cookie。",
          children: {
            isHookCookieDebugger: {
              value: false,
              name: "debugger",
              type: "switch",
            },
            isRefreshClearCookie: {
              value: false,
              name: "刷新清除cookie",
              type: "switch",
              describe: "清除当前域名下的cookie。",
            },
            inputCookieName: {
              value: "",
              name: "捕获cookie name",
              type: "input",
              inputType: "text",
              describe: "输入需要捕获的特定cookie名。",
            },
          },
        },
        /* setTimeout */
        isHookSetTimeout: {
          value: false,
          name: "hook setTimeout",
          type: "switch",
          describe: "setTimeout time为0 hook所有setTimeout。",
          children: {
            isHookSetTimeoutDebugger: {
              value: false,
              name: "debugger",
              type: "switch",
            },
            inputSetTimeOutTime: {
              value: 0,
              name: "捕获指定时间",
              type: "input",
              inputType: "number",
              describe: "setTimeout time必须大于0。否则hook所有。",
            },
          },
        },
        /* setInterval */
        isHookSetInterval: {
          value: false,
          name: "hook setInterval",
          type: "switch",
          describe: "setInterval time为0 hook所有setInterval。",
          children: {
            isHookSetIntervalDebugger: {
              value: false,
              name: "debugger",
              type: "switch",
            },
            inputSetIntervalTime: {
              value: 0,
              name: "捕获指定时间",
              type: "input",
              inputType: "number",
              describe: "setInterval time必须大于0。否则hook所有。",
            },
          },
        },
        /* alert */
        isHookAlert: {
          value: false,
          name: "hook alert",
          type: "switch",
          describe: "hook弹窗。",
          children: {
            isHookAlertDebugger: {
              value: false,
              name: "debugger",
              type: "switch",
            },
          },
        },
        /* alert */
        isHookHistory: {
          value: false,
          name: "hook history",
          type: "switch",
          describe: "hook历史返回记录。有的站点会自动返回。",
          children: {
            isHookHistoryDebugger: {
              value: false,
              name: "debugger",
              type: "switch",
            },
          },
        },
        /* function */
        isHookFunction: {
          value: false,
          name: "hook function",
          type: "switch",
          describe: "hook Function执行。",
          children: {
            isHookFunctionDebugger: {
              value: false,
              name: "debugger",
              type: "switch",
            },
            hookFunctionArgsName: {
              value: "",
              name: "参数名",
              type: "input",
              inputType: "text",
              describe: "没设置参数则hook所有。一般为debugger。",
            },
          },
        },
        /* header */
        isHookHeader: {
          value: false,
          name: "hook header",
          type: "switch",
          describe: "hook header设置。设置加密参数会遇到。",
          children: {
            isHookHeaderDebugger: {
              value: false,
              name: "debugger",
              type: "switch",
            },
            hookHeaderName: {
              value: "",
              name: "请求头参数名",
              type: "input",
              inputType: "text",
              describe: "没设置参数则hook所有。",
            },
          },
        },
        /* url */
        isHookUrl: {
          value: false,
          name: "hook url",
          type: "switch",
          describe: "hook url设置。",
          children: {
            isHookUrlDebugger: {
              value: false,
              name: "debugger",
              type: "switch",
            },
            hookUrlArgsName: {
              value: "",
              name: "url路径",
              type: "input",
              inputType: "text",
              describe: "没设置参数则hook所有。",
            },
          },
        },
        /* JSON.stringify */
        isHookStringify: {
          value: false,
          name: "hook JSON.stringify",
          type: "switch",
          describe: "hook JSON.stringify。在参数加密之后可能会遇到。",
          children: {
            isHookStringifyDebugger: {
              value: false,
              name: "debugger",
              type: "switch",
            },
          },
        },
        /* JSON.parse */
        isHookParse: {
          value: false,
          name: "hook JSON.parse",
          type: "switch",
          describe: "hook JSON.parse。在参数解密之后可能会遇到。",
          children: {
            isHookParseDebugger: {
              value: false,
              name: "debugger",
              type: "switch",
            },
          },
        },
        /* eval */
        isHookEval: {
          value: false,
          name: "hook eval",
          type: "switch",
          describe: "hook eval。动态执行JS。",
          children: {
            isHookEvalDebugger: {
              value: false,
              name: "debugger",
              type: "switch",
            },
          },
        },
      };
    },
    getValue: function (key, defaultValue) {
      return GM_getValue(key, defaultValue);
    },
    setValue: function (key, value) {
      GM_setValue(key, value);
    },
    delValue: function (key) {
      GM_deleteValue(key);
    },
  };
  const Dialog = (function () {
    class Dialog2 {
      constructor() {
        this.mask = document.createElement("div");
        this.dialogStyle = document.createElement("style");
        this.mask.classList.add("dialog-gcc-mask");
        this.setStyle(this.mask, {
          width: "100%",
          height: "100%",
          backgroundColor: "rgba(0, 0, 0, .6)",
          position: "fixed",
          left: "0px",
          top: "0px",
          bottom: "0px",
          right: "0px",
          "z-index": "9999999999999",
        });
        this.content = document.createElement("div");
        this.content.classList.add("dialog-gcc-container");
        this.setStyle(this.content, {
          "max-width": "350px",
          width: "90%",
          backgroundColor: "#fff",
          boxShadow: "0 0 2px #999",
          position: "absolute",
          left: "50%",
          top: "50%",
          transform: "translate(-50%,-50%)",
          borderRadius: "5px",
        });
        this.mask.appendChild(this.content);
      }

      middleBox(param) {
        this.content.innerHTML = "";
        if (param.hasOwnProperty("direction")) {
          this.content.setAttribute(
            "data-extension-direction",
            param.direction
          );
        }
        let title = "";
        if ({}.toString.call(param) === "[object String]") {
          title = param;
        } else if ({}.toString.call(param) === "[object Object]") {
          title = param.title;
        }
        document.body.appendChild(this.mask);
        this.title = document.createElement("div");
        this.title.classList.add("dialog-gcc-title");
        this.setStyle(this.title, {
          width: "100%",
          height: "40px",
          lineHeight: "40px",
          boxSizing: "border-box",
          "background-color": "#dedede",
          color: "#000",
          "text-align": "center",
          "font-weight": "700",
          "font-size": "17px",
          "border-radius": "4px 4px 0px 0px",
        });
        const span = document.createElement("span");
        span.innerText = title;
        span.setAttribute("langue-extension-text", "setting_modal_title");
        this.title.appendChild(span);
        this.closeBtn = document.createElement("span");
        this.closeBtn.innerText = "×";
        this.setStyle(this.closeBtn, {
          textDecoration: "none",
          color: "#000",
          position: "absolute",
          "inset-inline-end": "10px",
          top: "0px",
          fontSize: "25px",
          display: "inline-block",
          cursor: "pointer",
        });
        this.title.appendChild(this.closeBtn);
        this.content.appendChild(this.title);
        this.closeBtn.onclick = (e) => {
          e.stopPropagation();
          e.preventDefault();
          this.close();
        };
        
        // 确保能读取键盘事件
        this.mask.tabIndex = 0;
        this.mask.style.outline = "none";
        this.mask.focus();
      }

      showMake(param) {
        if (param.hasOwnProperty("styleSheet")) {
          this.dialogStyle.textContent = param.styleSheet;
        }
        document.querySelector("head").appendChild(this.dialogStyle);
        this.middleBox(param);
        this.dialogContent = document.createElement("div");
        this.dialogContent.classList.add("dialog-gcc-content");
        this.setStyle(this.dialogContent, {
          padding: "15px",
          "max-height": "400px",
          overflow: "auto",
        });
        this.dialogContent.innerHTML = param.content;
        this.content.appendChild(this.dialogContent);
        param.onContentReady(this);
      }

      updateTitle(title) {
        if (this.title) {
          this.title.innerText = title;
        }
      }

      close() {
        document.body.removeChild(this.mask);
        document.querySelector("head").removeChild(this.dialogStyle);
      }

      setStyle(ele, styleObj) {
        for (let attr in styleObj) {
          ele.style[attr] = styleObj[attr];
        }
      }
    }

    let dialog = null;
    return (function () {
      if (!dialog) {
        dialog = new Dialog2();
      }
      return dialog;
    })();
  })();
  const ToolBox = {
    createScript: function (jsCode) {
      const script = document.createElement("script");
      script.textContent = jsCode;
      (document.head || document.documentElement).appendChild(script);
      script.remove();
    },
    createRowItem: function (DataState) {
      let contentHtml = "";
      for (let key in DataState) {
        let item = DataState[key];
        let describe = "";
        if (item.describe) {
          describe = `<span class="__w_row_help">?<p class="__w_row_tooltip_text">${item.describe}</p></span>`;
        }
        if (item.type === "switch") {
          let subHtml = "";
          if (item.children && item.children.constructor === Object) {
            subHtml = this.createRowItem(item.children);
            subHtml = `<div class="__w_row_subItem">${subHtml}</div>`;
          }
          contentHtml += `
            <div>
              <div class="row-item setting">
                <div class="setting-name ${
                  subHtml !== "" ? "__w_cursor __w_retract" : ""
                }">${item.name}${describe}</div>
                <div class="setting-switch">
                  <input type="checkbox" id="${key}" /><label class="toggle" for="${key}"></label>
                </div>
              </div>
              ${subHtml}
            </div>`;
        } else if (item.type === "input") {
          let inputType = item.inputType;
          if (
            inputType === undefined ||
            inputType === "" ||
            !["text", "number"].includes(inputType)
          ) {
            console.log(`${key}未定义“inputType”，默认设置为：text。`);
            inputType = "text";
          }

          contentHtml += `
            <div class="row-item setting">
              <div class="setting-name">${item.name}${describe}</div>
              <div>
                <input type="${item.inputType}" id="${key}" class="__w_input __w_input_${inputType}" />
              </div>
            </div>`;
        }
      }
      return contentHtml;
    },
    listenOptionItem: function ($that, DataState) {
      for (let key in DataState) {
        let item = DataState[key];
        let ele = $that.dialogContent.querySelector("#" + key);
        if (item.type === "switch") {
          if (item.children && item.children.constructor === Object) {
            this.listenOptionItem($that, item.children);
          }
          ele.checked = item.value;
          ele.addEventListener("change", (e) => {
            item.value = e.target.checked;
          });
        } else if (item.type === "input") {
          ele.value = item.value;
          ele.addEventListener("change", (e) => {
            item.value = e.target.value;
          });
        }
      }
    },
    showSettingDialog: function () {
      const functionState = StorageUtil.getValue(
        StorageUtil.keys.functionState,
        StorageUtil.getDefaultFunctionState()
      );
      const styleSheet = `
			.row-item{
			    background: #ffffff;
			    padding: 15px;
			    border-radius: 10px;
			    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
			    transition: background 0.3s;
				  margin-bottom: 10px;
          position: relative;
			}
			
			.setting {
			    display: flex;
			    justify-content: space-between;
			    align-items: center;
			}
			
			.setting .setting-name{
			    flex: 1;
			    text-align: left;
			    font-size: 14px;
          position: relative;
			}
			
			.setting .setting-switch{
			    width: 60px;
			    display: flex;
			    justify-content: end;
			}
			      
			.recomment-item{
			    cursor: pointer;
			}
			.recomment-item:hover{
			    text-decoration: underline;
			}
			.ecomment-item-title{
			    font-size: 15px;
			    margin-bottom: 5px;
			}
			.ecomment-item-content{
			    font-size: 14px;
			}
			
			label {
			    font-size: 16px;
			    font-weight: bold;
			}
			.toggle {
			    width: 50px;
			    height: 25px;
			    background-color: #ccc;
			    border-radius: 15px;
			    position: relative;
			    cursor: pointer;
			    transition: background-color 0.3s;
			    display: inline-block;
			}
			.toggle:before {
			    content: '';
			    position: absolute;
			    width: 20px;
			    height: 20px;
			    background-color: white;
			    border-radius: 50%;
			    top: 50%;
			    left: 3px;
			    transform: translateY(-50%);
			    transition: 0.2s;
			}
			input:checked + .toggle {
			    background-color: #4CAF50;
			}
			input:checked + .toggle:before {
			    transform: translate(24px, -50%);
			}
			input {
			    display: none;
			}
			/*white自定义按钮*/
      .__w_btn-primary {
          background-color: #3b82f6;
          color: white;
      }
      .__w_btn-times::before {
          content: "✕";
      }
      .__w_btn-sm {
          padding: 8px 16px;
          font-size: 14px;
      }
      .__w_btn-plus::before {
          content: "+";
      }
      .__w_BTN {
          border: none;
          border-radius: 6px;
          padding: 2px 8px;
          font-size: 14px;
          font-weight: 500;
          cursor: pointer;
          transition: all 0.2s ease;
          display: flex;
          align-items: center;
          justify-content: center;
          gap: 8px;
      }
      .__w_BTN:not(.btn-disabled):hover {
          transform: translateY(-2px);
          box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
      }
      .__w_BTN:not(.btn-disabled):active {
          transform: translateY(0);
          box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
      }
      .__w_btn-reset {
        background-color: #ef4444;
        color: white;
      }
      .__w_btn-refresh::before {
        content: "↺";
      }
      .__w_input{
          display: inline-block;
          height: 28px;
          border: 1px solid #ccc;
          border-radius: 4px;
      }
      .__w_input:focus {
        outline: 2px solid #4CAF50; 
        outline-offset: 1px;
      }
      .__w_input_text{
          width: 60px;
          padding: 0px 15px;
          font-size: 14px;
      }
      .__w_input_number{
          width: 60px;
          font-size: 16px;
          padding: 0px 15px;
      }
      .__w_retract::before{
        content: "▸";
        position: absolute;
        left: -14px;
      }
      .__w_expand::before{
        content: "▾";
        position: absolute;
        left: -14px;
      }
      .__w_row_subItem{
        display:none;
        margin-left: 15px;
        color: #399845;
      }
      .__w_cursor{
        cursor: pointer;
      }
      .__w_row_help {
        display: inline-block;
        width: 18px;
        height: 18px;
        border-radius: 50%;
        background-color: #606266;
        color: #fff;
        text-align: center;
        line-height: 18px;
        font-size: 12px;
        font-weight: bold;
        margin-left: 5px;
        cursor: help;
        position: relative;
      }
      .__w_row_help .__w_row_tooltip_text {
        visibility: hidden;
        word-wrap: break-word;
        min-width: 150px;
        max-width: 300px;
        max-height: 200px;
        min-height: 15px;
        background-color: rgb(73, 68, 68);
        color: #fff;
        text-align: center;
        padding: 5px;
        border-radius: 6px;
        
        /* 定位 */
        position: absolute;
        z-index: 1;
        opacity: 0;
        transition: opacity 1s;
        transition-delay: 1s;

        top: 100%;
        left: 50%; 
        margin-left: -100px; /* 使用一半宽度 (120/2 = 60) 来居中提示工具 */
      }
      .__w_row_help:hover .__w_row_tooltip_text{
         visibility: visible;
         opacity: 1;
         transition-delay: 0s;
      }
      .__w_row_help .__w_row_tooltip_text::after{
        content: " ";
        position: absolute;
        bottom: 100%;  /* 提示工具头部 */
        left: 50%;
        margin-left: -5px;
        border-width: 5px;
        border-style: solid;
        border-color: transparent transparent black transparent;
      }
		`;
      let contentHtml = this.createRowItem(functionState);
      const content = `
			${contentHtml}
			<div class="row-item setting">
                <button class="__w_BTN __w_btn-primary __w_btn-sm __w_btn-plus" id="__w_SAVE">
                    <span>保存</span>
                </button>
                <button class="__w_BTN __w_btn-sm __w_btn-reset __w_btn-refresh" id="__w_RESET">
                    <span>重置</span>
                </button>
                <button class="__w_BTN __w_btn-sm __w_btn-times" id="__w_CANCEL">
                    <span>取消</span>
                </button>
            </div>
            `;
      Dialog.showMake({
        title: "Settings",
        content,
        styleSheet,
        onContentReady: function ($that) {
          $that.dialogContent
            .querySelectorAll(".__w_cursor")
            .forEach((item) => {
              item.addEventListener("click", (e) => {
                e.stopPropagation();
                e.preventDefault();
                let parent;
                if (e.target.tagName === "SPAN") {
                  parent = e.target.parentNode.parentNode.parentNode;
                } else if (e.target.tagName === "DIV") {
                  parent = e.target.parentNode.parentNode;
                } else {
                  return;
                }
                const sub = parent.querySelector(".__w_row_subItem");
                const display = sub.style.display;
                sub.style.display =
                  display === "" || display === "none" ? "block" : "none";
                e.target.classList.toggle("__w_retract");
                e.target.classList.toggle("__w_expand");
              });
            });

          const save = $that.dialogContent.querySelector("#__w_SAVE");
          const reset = $that.dialogContent.querySelector("#__w_RESET");
          const cancel = $that.dialogContent.querySelector("#__w_CANCEL");
          save.addEventListener("click", (e) => {
            e.stopPropagation();
            e.preventDefault();
            StorageUtil.setValue(StorageUtil.keys.functionState, functionState);
            $that.close();
            this.onClose();
          });
          reset.addEventListener("click", (e) => {
            e.stopPropagation();
            e.preventDefault();
            StorageUtil.delValue(StorageUtil.keys.functionState);
            $that.close();
            this.onClose();
          });
          cancel.addEventListener("click", (e) => {
            $that.close();
          });
          ToolBox.listenOptionItem($that, functionState);

          $that.mask.addEventListener("keydown", (e) => {
            if ((e.ctrlKey || e.metaKey) && e.key === "s") {
              e.preventDefault();
              StorageUtil.setValue(
                StorageUtil.keys.functionState,
                functionState
              );
              $that.close();
              this.onClose();
            }
          });
        },
        onClose: function () {
          location.reload();
        },
      });
    },
    run: function () {
      return new Promise((resolve) => {
        GM_registerMenuCommand("Setting", () => {
          this.showSettingDialog();
        });
      });
    },
  };

  (async () => {
    await ToolBox.run();
  })();

  (() => {
    const Value = StorageUtil.getValue(
      StorageUtil.keys.functionState,
      StorageUtil.getDefaultFunctionState()
    );

    /*  hook cookie */
    if (Value.isHookCookie.value) {
      console.log("开启 hook cookies");
      const option = Value.isHookCookie;
      const children = option.children;
      const _debugger = children.isHookCookieDebugger.value;
      /* 清空cookie */
      if (children.isRefreshClearCookie.value) {
        console.log("开启 清空cookie");
        const jsCode = `
          ((()=>{
            document.cookie ="expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
          })());`;
        ToolBox.createScript(jsCode);
      }

      const cookieName = children.inputCookieName.value;
      const jsCode = `
        ((function () {
          'use strict';
          var cookieTemp = '';
          const cookieName = "${cookieName}";
          const _debugger = ${_debugger};
          Object.defineProperty(document, 'cookie', {
            set: function (val) {
              // hook指定cookie键
              console.log('Hook捕获到cookie设置->', val);
              if (_debugger && cookieName === ""){
                debugger;
              }
              if (_debugger && cookieName && val.indexOf(cookieName) !== -1) {
                debugger;
              }
              cookieTemp = val;
              return val;
            }, get: function () {
              return cookieTemp;
            },
          });
        })());`;
      ToolBox.createScript(jsCode);
    }
    /*  hook setTimeout */
    if (Value.isHookSetTimeout.value) {
      console.log("开启 hook setTimeout");
      const option = Value.isHookSetTimeout;
      const children = option.children;
      const _debugger = children.isHookSetTimeoutDebugger.value;
      let numberTime = parseInt(children.inputSetTimeOutTime.value);
      numberTime = numberTime == NaN || numberTime <= 0 ? 0 : numberTime;
      const jsCode = `
        (function() {
          'use strict';
          const _setTimeout = setTimeout;
          const numberTime = ${numberTime};
          const _debugger = ${_debugger};
          Object.defineProperty(window, "setTimeout", {
            value: function(func, time) {
              console.log("hook setTimeout time：" + time);
              if (_debugger && numberTime === 0){
                debugger;
                return function() {};
              }
              if (_debugger && numberTime && time === numberTime) {
                debugger;
                return function() {};
              }
              return _setTimeout(func, time);
            },
              writable: false,
            });
          })();`;
      ToolBox.createScript(jsCode);
    }
    /*  hook setInterval */
    if (Value.isHookSetInterval.value) {
      console.log("开启 hook setInterval");
      const option = Value.isHookSetInterval;
      const children = option.children;
      const _debugger = children.isHookSetIntervalDebugger.value;
      let numberTime = parseInt(children.inputSetIntervalTime.value);
      numberTime = numberTime == NaN || numberTime <= 0 ? 0 : numberTime;

      const jsCode = `
        (function() {
          const _setInterval = setInterval;
          const numberTime = ${numberTime};
          const _debugger = ${_debugger};
          Object.defineProperty(window, "setInterval", {
            value: function(func, time) {
              console.log("hook setInterval time：" + time);
              if (_debugger && numberTime === 0){
                debugger;
                return function() {};
              }
              if (_debugger && numberTime && time === numberTime) {
                debugger;
                return function() {};
              }
              return _setInterval(func, time);
            },
            writable: false,
          });
         })();`;
      ToolBox.createScript(jsCode);
    }
    /*  hook alert */
    if (Value.isHookAlert.value) {
      console.log("开启 hook alert");
      const option = Value.isHookAlert;
      const children = option.children;
      const _debugger = children.isHookAlertDebugger.value;
      const jsCode = `
        (function() {
          'use strict';
          const _debugger = ${_debugger};
          Object.defineProperty(window, "alert", {
            value: function(text) {
              console.log("hook alert："+text);
              if(_debugger)debugger;
              return function () {};
            },
            writable: false,
          });
        })();`;
      ToolBox.createScript(jsCode);
    }
    /*  hook history back */
    if (Value.isHookHistory.value) {
      console.log("开启 hook history");
      const option = Value.isHookHistory;
      const children = option.children;
      const _debugger = children.isHookHistoryDebugger.value;
      const jsCode = `
        ((function() {
          'use strict';
          const _debugger = ${_debugger};
          Object.defineProperty(window.history, "back", {
            value: function() {
              console.log("hook history back");
              if(_debugger)debugger;
              return function () {};
            },
            writable: false,
          });
        })());`;
      ToolBox.createScript(jsCode);
    }
    /* hook function */
    if (Value.isHookFunction.value) {
      console.log("开启 hook function");
      const option = Value.isHookFunction;
      const children = option.children;
      const argsName = children.hookFunctionArgsName.value;
      const _debugger = children.isHookFunctionDebugger.value;
      const jsCode1 = `
        ((() => {
          'use strict';
          const argsName = "${argsName}";
          const _debugger = ${_debugger};
          Function.prototype._constructor = Function.prototype.constructor;
          Object.defineProperty(Function.prototype, "constructor", {
            value: function () {
              console.log("hook Function:" + JSON.stringify(arguments));
              if (_debugger && argsName === "") {
                debugger;
                return;
              }
              if (_debugger && arguments && typeof arguments[0] == "string") {
                if ("debugger" == arguments[0]) {
                  debugger;
                  return;
                }
              }
              return Function.prototype._constructor.apply(this, arguments);
            },
            writable: false,
          });
        })());`;
      const jsCode2 = `
        ((() => {
          'use strict';
          const argsName = "${argsName}";
          const _debugger = ${_debugger};

          window._fun = window.Function;
          var myfun = function () {
            var args = Array.prototype.slice.call(arguments, 0, -1).join(","),
              src = arguments[arguments.length - 1];
            console.log("===============hook Function start ===============");
            console.log(src);
            console.log("===============hook Function end ===============");
            if(_debugger){
              debugger;
              return;
            };
            return window._fun.apply(this, arguments);
          };
          // 屏蔽js中对原生函数native属性的检测
          myfun.toString = function () {
            return window._fun + "";
          };
          Object.defineProperty(window, "Function", {
            value: myfun,
            writable: false,
          });
        })());`;
      ToolBox.createScript(jsCode1);
    }
    /* hook header */
    if (Value.isHookHeader.value) {
      console.log("开启 hook header");
      const option = Value.isHookHeader;
      const children = option.children;
      const argsName = children.hookHeaderName.value;
      const _debugger = children.isHookHeaderDebugger.value;
      const jsCode = `
        ((() => {
          "use strict";
          const setHeader = window.XMLHttpRequest.prototype.setRequestHeader;
          const argsName = "${argsName}";
          const _debugger = ${_debugger};
          Object.defineProperty(
            window.XMLHttpRequest.prototype,
            "setRequestHeader",
            {
              value: function (key, value) {
                console.log("hook header key:" + key + "\tvalue:" + value);
                if (_debugger && argsName === "") {
                  debugger;
                }
                if (_debugger && key === argsName) {
                  debugger;
                }
                return setHeader.apply(this, arguments);
              },
              writable: false,
            }
          );
        })());`;
      ToolBox.createScript(jsCode);
    }
    /* hook url */
    if (Value.isHookUrl.value) {
      console.log("开启 hook url");
      const option = Value.isHookUrl;
      const children = option.children;
      const argsName = children.hookUrlArgsName.value;
      const _debugger = children.isHookUrlDebugger.value;
      const jsCode = `
        ((() => {
          "use strict";
          const open = window.XMLHttpRequest.prototype.open;
          const argsName = "${argsName}";
          const _debugger = ${_debugger};
          Object.defineProperty(
            window.XMLHttpRequest.prototype,
            "open",
            {
              value: function (method, url, async) {
                console.log("hook header method:" + method + "\turl:" + url);
                if (_debugger && argsName === "") {
                  debugger;
                }
                if (_debugger && url.indexOf(argsName) != -1) {
                  debugger;
                }
                return open.apply(this, arguments);
              },
              writable: false,
            }
          );
        })());`;
      ToolBox.createScript(jsCode);
    }
    /* hook JSON.stringify */
    if (Value.isHookStringify.value) {
      const option = Value.isHookStringify;
      const children = option.children;
      const _debugger = children.isHookStringifyDebugger.value;
      console.log("开启 hook JSON.stringify");
      const jsCode = `
        ((() => {
          "use strict";
          const _debugger = ${_debugger};
          const stringify = JSON.stringify;
          Object.defineProperty(JSON, "stringify", {
            value: function (params) {
              console.log("Hook JSON.stringify: ", params);
              if(_debugger)debugger;
              return stringify(params);
            },
            writable: false,
          });
        })());`;

      ToolBox.createScript(jsCode);
    }
    /* hook JSON.parse */
    if (Value.isHookParse.value) {
      const option = Value.isHookParse;
      const children = option.children;
      const _debugger = children.isHookParseDebugger.value;
      console.log("开启 hook JSON.stringify");
      const jsCode = `
        ((() => {
          "use strict";
          const _debugger = ${_debugger};
          const stringify = JSON.parse;
          Object.defineProperty(JSON, "parse", {
            value: function (params) {
              console.log("Hook JSON.parse: ", params);
              if(_debugger)debugger;
              return stringify(params);
            },
            writable: false,
          });
        })());`;

      ToolBox.createScript(jsCode);
    }
    /* hook eval */
    if (Value.isHookEval.value) {
      const option = Value.isHookEval;
      const children = option.children;
      const _debugger = children.isHookEvalDebugger.value;
      console.log("开启 hook eval");
      const jsCode = `
        ((() => {
          "use strict";
          const _debugger = ${_debugger};
          window.__w_eval = window.eval;
          var myeval = function (src) {
            console.log("===============hook eval start ===============");
            console.log(src);
            console.log("===============hook eval end ===============");
            if(_debugger)debugger;
            return window.__w_eval(src);
          };
          const _myeval = myeval.bind(null);
          _myeval.toString = window.__w_eval.toString;
          Object.defineProperty(window, "eval", { value: _myeval });
        })());`;
      ToolBox.createScript(jsCode);
    }
  })();
})();
